#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

// 用户名和密码
#define USERNAME "user4"
#define PASSWORD "pass4"
#define SERVEIP "127.0.0.4"

// 服务端端口号
#define SERVER_PORT 12346

// 输入消息大小范围
#define BUFFSIZE 1024

void error(const char *msg) {
    perror(msg);
    exit(1);
}

void computeTime(){
    time_t rawtime;
    struct tm *timeinfo;
    char timeBuffer[20]; // 用于存储格式化后的时间字符串，长度为 20 是因为需要包含年月日时分秒及分隔符

    // 获取当前时间的秒数
    time(&rawtime);

    // 将秒数转换为本地时间
    timeinfo = localtime(&rawtime);

    // 格式化时间字符串
    strftime(timeBuffer, sizeof(timeBuffer), "%Y:%m:%d:%H:%M:%S", timeinfo);

    // 输出格式化后的时间字符串
    printf("%s :", timeBuffer);
}

void *server_function(void *arg) {
    int server_socket, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFSIZE];

    // 创建套接字
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0)
        error("无法创建套接字");

    // 设置服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVEIP);
    server_addr.sin_port = htons(SERVER_PORT);

    // 绑定套接字
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
        error("绑定失败");

    // 监听
    if (listen(server_socket, 5) < 0)
        error("监听失败");

    // printf("服务器启动，等待客户端连接...\n");

    char userName[BUFFSIZE];
    char message[BUFFSIZE];
    char *colonPosition;
    size_t colonIndex;

    // 循环接受客户端连接
    while (1) {
        // 接受客户端连接
        client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
        if (client_socket < 0) {
            printf("接受连接失败\n");
            continue; // 继续等待下一个连接
        }

        // printf("客户端连接成功！\n");

        // 处理客户端的消息
        // 在这里添加你需要的业务逻辑

        while (1) {
            ssize_t byteRead = recv(client_socket, buffer, BUFFSIZE, 0);
            if(byteRead == -1){
                printf("服务器：接收套接字内容错误\n");
                return NULL;
            }

            colonPosition = strchr(buffer, ':');
            colonIndex = colonPosition - buffer;
            // 拷贝用户名部分
            strncpy(userName, buffer, colonIndex);
            userName[colonIndex] = '\0';  // 添加字符串结束符
            // 将message置空
            memset(message, 0, sizeof(message)); 
            // 拷贝内容部分
            strcpy(message, colonPosition + 1);  


            // 调用显示时间函数
            computeTime();
            printf("%s：%s\n",userName,message);
            // 将buffer置空
            memset(buffer, 0, sizeof(buffer));

            if (strcmp(message, "exit") == 0) {
                printf("对方断开连接\n");
                break; // 跳出内层循环，关闭当前连接
            }
        }

        // 关闭当前连接的套接字
        close(client_socket);
    }

    // 关闭服务器套接字
    close(server_socket);

    return NULL;
}

void *client_function(void *arg) {
    char *connection_info = (char *)arg;
    char username[50], password[50], ip[50];
    int port;
    char input[BUFFSIZE];
    char myInput[BUFFSIZE];
    sscanf(connection_info, "%[^:]:%[^@]@%[^:]:%d", username, password, ip, &port);

    // 模拟登录
    if (strcmp(username, USERNAME) != 0 || strcmp(password, PASSWORD) != 0) {
        printf("登录失败：用户名或密码错误\n");
        return NULL;
    }

    int client_socket;
    struct sockaddr_in server_addr;

    // 尝试连接服务器，最多尝试三次
    int max_attempts = 3;
    for (int attempt = 1; attempt <= max_attempts; ++attempt) {
        // 创建套接字
        client_socket = socket(AF_INET, SOCK_STREAM, 0);
        if (client_socket < 0)
            error("无法创建套接字");

        // 设置服务器地址结构
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = inet_addr(ip);
        server_addr.sin_port = htons(port);

        // 连接到服务器
        if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
            printf("连接失败，尝试重连（%d/%d）...\n", attempt, max_attempts);
            close(client_socket);
            if (attempt < max_attempts) {
                // 延迟5秒再次尝试
                sleep(5);
            } else {
                error("无法连接到服务器");
            }
        } else {
            // 连接成功
            printf("登录成功，连接到对方服务器！\n");

            // 在这里可以添加客户端发送消息的逻辑
            printf("请输入要发送的消息（输入 'exit' 断开连接）\n");
            while (1)
            {
                /* 用户键盘输入 */
                fgets(myInput, sizeof(input), stdin);
                myInput[strcspn(myInput, "\n")] = '\0';  // 移除输入中的换行符

                /* 在消息前加上用户名 */
                sprintf(input, "%s:%s", USERNAME, myInput);
                /* 发送数据 */
                ssize_t byteSend = send(client_socket, input, strlen(input), 0);
                
                /* 检查是否需要断开连接 */
                if (strcmp(myInput, "exit") == 0) {
                    printf("断开连接\n");
                    break;
                }
                /* 显示发送数据的信息 */
                computeTime();
                printf("%s\n",input);
            }

            close(client_socket);
            return NULL;
        }
    }

    return NULL;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "用法: %s <用户：密码@ip地址:端口>\n", argv[0]);
        exit(1);
    }

    // 创建线程的变量
    pthread_t server_thread, client_thread;

    // 创建服务器线程
    if (pthread_create(&server_thread, NULL, server_function, NULL) != 0) {
        error("无法创建服务器线程");
    }

    // 将服务器线程设置为后台线程
    if (pthread_detach(server_thread) != 0) {
        error("无法设置服务器线程为后台线程");
    }

    // 创建客户端线程
    if (pthread_create(&client_thread, NULL, client_function, argv[1]) != 0) {
        error("无法创建客户端线程");
    }

    // 等待线程结束
    pthread_join(server_thread, NULL);
    pthread_join(client_thread, NULL);

    return 0;
}
